/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2019 HUST Dian Group
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Original Author: Pengyu Liu <eicliupengyu@gmail.com>
 */
#include "ns3/log.h"
#include "robo-supply.h"
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("RoboSupply");
NS_OBJECT_ENSURE_REGISTERED (RoboSupply);
RoboSupply::RoboSupply (void)
{
  NS_LOG_FUNCTION (this);
  AddCollisionCallback (MakeCallback (&RoboSupply::HandleCollision, this));
  m_initPlot = MakeCallback (&RoboSupply::InitPlot, this);
  m_updatePlot = MakeCallback (&RoboSupply::PlotSelf, this);
  m_ammoNum[AmmoType17] = 200;
  m_ammoNum[AmmoType42] = 0;
  m_incAmmoTimer = Timer (Timer::CANCEL_ON_DESTROY);
  m_incAmmoTimer.SetFunction (&RoboSupply::GenAmmo, this);
  m_incAmmoTimer.SetDelay (Seconds (10));
  m_incAmmoTimer.Schedule ();
}

RoboSupply::~RoboSupply (void)
{
  NS_LOG_FUNCTION (this);
}
TypeId
RoboSupply::GetTypeId (void)
{
  static TypeId tid = TypeId ("ns3::RoboSupply")
                          .SetParent<RoboActor> ()
                          .SetGroupName ("Robo")
                          .AddConstructor<RoboSupply> ()

      ;
  return tid;
}
TypeId
RoboSupply::GetInstanceTypeId (void) const
{
  return GetTypeId ();
}
void
RoboSupply::HandleCollision (Ptr<RoboActor> oth)
{
  Ptr<RoboBase> robo = oth->GetObject<RoboBase> ();
  if (!robo || robo->m_team != m_team)
    {
      return;
    }
  switch (robo->GetRoboType ())
    {
    case RoboTypeHero:
    case RoboTypeInfantry:
      case RoboTypeEngineer: {
        if (m_incLife && !robo->m_isDestroy && Simulator::Now () >= robo->m_nextLifeInc)
          {
            robo->m_life = std::min (
                robo->m_life + gRoboMaxLife[robo->m_roboType][robo->m_maxLifeLevel] * .05f,
                (float) gRoboMaxLife[robo->m_roboType][robo->m_maxLifeLevel]);
            robo->m_nextLifeInc = Simulator::Now () + Seconds (1);
          }
        break;
      }

    default:
      break;
    }
}
void
RoboSupply::SetTeam (uint8_t teamId)
{
  NS_LOG_FUNCTION (this << (int) teamId);
  m_team = teamId;
}
uint8_t
RoboSupply::GetTeam (void) const
{
  return m_team;
}
int
RoboSupply::GetAmmoNum (AmmoType ammoType)
{
  return m_ammoNum[ammoType];
}
int
RoboSupply::AskForAmmo (Ptr<RoboBase> robo, int ammoNum, AmmoType ammoType)
{
  if (robo->m_team != m_team || robo->m_roboType == RoboTypeSentinel ||
      robo->m_roboType == RoboTypeUVA)
    {
      return 0;
    }
  int num = std::min (ammoNum, m_ammoNum[ammoType]);
  num = std::min (num, gWeaponMaxAmmoNum[robo->m_roboType][ammoType] -
                           robo->m_weapon[ammoType].m_ammoNumber);
  m_ammoNum[ammoType] -= num;
  robo->m_weapon[ammoType].m_ammoNumber += num;
  return num;
}

void
RoboSupply::GenAmmo (void)
{
  m_ammoNum[AmmoType17] += 50;
  m_incAmmoTimer.Schedule ();
}

void
RoboSupply::InitPlot (FILE *fp)
{
  fprintf (fp, "as:%u@%d@", m_team, m_incLife);
  for (auto &p : m_boundaryPoint)
    {
      auto real_point = ConvCoordinate (m_globalLocation, m_globalRotation, p);
      fprintf (fp, "%.3f:%.3f|", real_point.m_x, real_point.m_y);
    }
  fprintf (fp, "\n");
}

void
RoboSupply::PlotSelf (FILE *fp)
{
  fprintf (fp, "sp:%d@%d@%d\n", m_team, m_ammoNum[AmmoType17], m_ammoNum[AmmoType42]);
}
} // namespace ns3
